package org.fujay.langchain4jserver.domain.conversation.entity;

import lombok.Getter;
import lombok.ToString;
import org.fujay.langchain4jserver.domain.conversation.vo.MessageId;
import org.fujay.langchain4jserver.domain.conversation.vo.MessageType;
import org.fujay.langchain4jserver.domain.conversation.vo.TokenUsage;
import org.springframework.util.Assert;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 消息实体
 */
@Getter
@ToString
public class MessageEntity {

    private final MessageId id;
    private final MessageType type;
    private final String content;
    private final LocalDateTime timestamp;
    private final TokenUsage tokenUsage;
    private final Map<String, Object> metadata;
    private final List<String> imageUrls;

    private final transient boolean isNew;

    private MessageEntity(
            MessageId id,
            MessageType type,
            String content,
            LocalDateTime timestamp,
            TokenUsage tokenUsage,
            Map<String, Object> metadata,
            List<String> imageUrls,
            boolean isNew) {
        Assert.notNull(id, "Message ID cannot be null");
        Assert.notNull(type, "Message type cannot be null");
        Assert.notNull(content, "Message content cannot be null");
        Assert.notNull(timestamp, "Message timestamp cannot be null");

        this.id = id;
        this.type = type;
        this.content = content;
        this.timestamp = timestamp;
        this.tokenUsage = tokenUsage;
        this.metadata = metadata;
        this.imageUrls = imageUrls;
        this.isNew = isNew;
    }

    /**
     * 创建新消息 (AI或用户)
     */
    public static MessageEntity createNew(
            MessageType type,
            String content,
            TokenUsage tokenUsage,
            Map<String, Object> metadata,
            List<String> imageUrls) {
        Assert.isTrue(
                type == MessageType.AI || type == MessageType.USER,
                "Only AI or USER message can be created this way");
        return new MessageEntity(
                MessageId.create(),
                type,
                content,
                LocalDateTime.now(),
                tokenUsage,
                metadata,
                imageUrls,
                true);
    }

    /**
     * 加载已存在的消息 (供 Repository 使用)
     */
    public static MessageEntity load(
            MessageId id,
            MessageType type,
            String content,
            LocalDateTime timestamp,
            TokenUsage tokenUsage,
            Map<String, Object> metadata,
            List<String> imageUrls) {
        return new MessageEntity(id, type, content, timestamp, tokenUsage, metadata, imageUrls, false);
    }

    public static MessageEntity createUserMessage(MessageId id, String content) {
        return createUserMessage(id, content, null, null);
    }

    public static MessageEntity createUserMessage(
            MessageId id, String content, List<String> imageUrls) {
        return createUserMessage(id, content, imageUrls, null);
    }

    // --- Static factory methods WITH ID ---
    // Used by Aggregate Root after generating an ID

    public static MessageEntity createUserMessage(
            MessageId id, String content, List<String> imageUrls, Map<String, Object> metadata) {
        return new MessageEntity(
                id, MessageType.USER, content, LocalDateTime.now(), null, metadata, imageUrls, true);
    }

    public static MessageEntity createAiMessage(MessageId id, String content) {
        return createAiMessage(id, content, null, null);
    }

    public static MessageEntity createAiMessage(
            MessageId id, String content, TokenUsage tokenUsage, Map<String, Object> metadata) {
        return new MessageEntity(
                id, MessageType.AI, content, LocalDateTime.now(), tokenUsage, metadata, null, true);
    }

    public static MessageEntity createSystemMessage(MessageId id, String content) {
        return createSystemMessage(id, content, null);
    }

    public static MessageEntity createSystemMessage(
            MessageId id, String content, Map<String, Object> metadata) {
        return new MessageEntity(
                id, MessageType.SYSTEM, content, LocalDateTime.now(), null, metadata, null, true);
    }

    // --- Static factory methods WITHOUT ID (DEPRECATED/ PROBLEMATIC) ---
    // Keep the existing ones that throw exceptions for now, or remove them if
    // preferred.
    public static MessageEntity createUserMessage(String content) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createUserMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createUserMessage(String content, List<String> imageUrls) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createUserMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createUserMessage(
            String content, List<String> imageUrls, Map<String, Object> metadata) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createUserMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createAiMessage(String content) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createAiMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createAiMessage(
            String content, TokenUsage tokenUsage, Map<String, Object> metadata) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createAiMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createSystemMessage(String content) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createSystemMessage(content,...)' in Message needs ID assignment logic.");
    }

    public static MessageEntity createSystemMessage(String content, Map<String, Object> metadata) {
        // ... existing implementation throwing exception ...
        throw new UnsupportedOperationException(
                "Static factory 'createSystemMessage(content,...)' in Message needs ID assignment logic.");
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        MessageEntity message = (MessageEntity) o;
        return Objects.equals(id, message.id);
    }
}
